#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ths_ini.h"
#include "ths_test.h"


typedef struct
{
    int version;
    const char* name;
    const char* email;
} configuration;

static int User;
static char Prev_section[50];

static int handler(void* user, const char* section, const char* name,
                   const char* value)
{
    configuration* pconfig = (configuration*)user;

    #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
    if (MATCH("protocol", "version")) {
        pconfig->version = atoi(value);
    } else if (MATCH("user", "name")) {
        pconfig->name = strdup(value);
    } else if (MATCH("user", "email")) {
        pconfig->email = strdup(value);
    } else {
        return 0;  /* unknown section/name, error */
    }
    return 1;
}

static int ini_example_dumper(void* user, const char* section, const char* name,
                  const char* value)
{
    static char prev_section[50] = "";

    if (strcmp(section, prev_section)) {
        printf("%s[%s]\n", (prev_section[0] ? "\n" : ""), section);
        strncpy(prev_section, section, sizeof(prev_section));
        prev_section[sizeof(prev_section) - 1] = '\0';
    }
    printf("%s = %s\n", name, value);
    return 1;
}

static void ths_ini_example() {
    configuration config;

    if (ini_parse("./test/data/ini/example/test.ini", handler, &config) < 0) {
        printf("Can't load 'test.ini'\n");
        return;
    }

    printf("Config loaded from 'test.ini': version=%d, name=%s, email=%s\n",
        config.version, config.name, config.email);

}

static void ths_ini_test_dumper() {
    if (ini_parse("./test/data/ini/example/test.ini", ini_example_dumper, NULL) < 0) {
        printf("Can't load 'test.ini'\n");
        return;
    }
}

static int ini_test_dumper(void* user, const char* section, const char* name,
           const char* value)
{
    User = (int)user;
    if (strcmp(section, Prev_section)) {
        printf("... [%s]\n", section);
        strncpy(Prev_section, section, sizeof(Prev_section));
        Prev_section[sizeof(Prev_section) - 1] = '\0';
    }
    printf("... %s=%s;\n", name, value);

    return strcmp(name, "user")==0 && strcmp(value, "parse_error")==0 ? 0 : 1;
}

static void ths_ini_parse_test(const char* fname) {
    static int u = 100;
    int e;

    *Prev_section = '\0';
    e = ini_parse(fname, ini_test_dumper, (void*)u);
    printf("%s: e=%d user=%d\n", fname, e, User);
    u++;
}


void ths_ini_test_all() {
	ths_ini_example();
	ths_ini_test_dumper();

	ths_ini_parse_test("./test/data/ini/test/no_file.ini");
	ths_ini_parse_test("./test/data/ini/test/normal.ini");
	ths_ini_parse_test("./test/data/ini/test/bad_section.ini");
	ths_ini_parse_test("./test/data/ini/test/bad_comment.ini");
	ths_ini_parse_test("./test/data/ini/test/user_error.ini");
	ths_ini_parse_test("./test/data/ini/test/multi_line.ini");
	ths_ini_parse_test("./test/data/ini/test/bad_multi.ini");
	ths_ini_parse_test("./test/data/ini/test/bom.ini");
}
